package cn.ximart.passport.service.impl;

import cn.ximart.passport.ex.ServiceException;
import cn.ximart.passport.mapper.AdminMapper;
import cn.ximart.passport.mapper.AdminRoleMapper;
import cn.ximart.passport.pojo.dto.AdminAddNewDTO;
import cn.ximart.passport.pojo.dto.AdminLoginDTO;
import cn.ximart.passport.pojo.entity.Admin;
import cn.ximart.passport.pojo.entity.AdminRole;
import cn.ximart.passport.pojo.vo.AdminListItemVO;
import cn.ximart.passport.security.AdminDetails;
import cn.ximart.passport.service.IAdminService;
import cn.ximart.passport.util.JwtUtils;
import cn.ximart.passport.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {

    @Autowired
    private AdminMapper mapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private AdminRoleMapper adminRoleMapper;

    @Override
    @Transactional
    public void addNew(AdminAddNewDTO adminAddNewDTO) {

        log.debug("即将进行添加用户的操作，接收到的数据为{}", adminAddNewDTO);
        String username = adminAddNewDTO.getUsername();
        int count = mapper.countByUsername(username);
        if (count > 0) {
            String message = "用户名为【" + username + "】的用户已经存在";
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        Admin admin = new Admin();

        /*当前方法的参数值复制到实体类型的对象中*/
        BeanUtils.copyProperties(adminAddNewDTO, admin);

        /*补全属性值（不由客户提交的属性值应该在插入之前补全）*/
        admin.setLoginCount(0);
        admin.setLastLoginIp(null);
        admin.setGmtLastLogin(null);


        /*将原密码从Admin对象中取出，加密后再存入到Admin对象中*/
        String rawPassword = admin.getPassword();
        String encodePassword = passwordEncoder.encode(rawPassword);
        admin.setPassword(encodePassword);


        /*将用户数据写入到数据库中*/
        log.debug("即将插入用户数据，接收到的数据为{}", admin);
        int rows = mapper.insert(admin);
        if (rows != 1) {
            String message = "添加失败，服务器繁忙，请稍后再试";
            throw new ServiceException(ServiceCode.ERR_UNKNOWN, message);
        }

        /*插入管理员与角色的关联数据，使得以上添加的管理员是被分配了角色的*/
        AdminRole adminRole = new AdminRole();
        adminRole.setAdminId(admin.getId());
        adminRole.setRoleId(2L);
        log.debug("即将向管理员与角色的关联表中写入数据：{}",adminRole);
        int row = adminRoleMapper.insert(adminRole);
        if(row!=1){
            String message = "添加失败，服务器繁忙，请稍后再试,【错误码：1】";
            throw new ServiceException(ServiceCode.ERR_INSERT,message);
        }
    }

    @Override
    public String login(AdminLoginDTO adminLoginDTO) {
        log.debug("开始处理管理员登录的业务，参数：{}", adminLoginDTO);

        //调用AuthenticationManager执行Spring Security的认证
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                //           ^认证书
                adminLoginDTO.getUsername(), adminLoginDTO.getPassword()
        );
        Authentication loginResult = authenticationManager.authenticate(authentication);

        //以上调用的authenticate()方法是会报异常的方法，如果执行到此处，则说明用户名与密码是匹配的
        log.debug("登录成功！认证方法返回：{}>>>{}", loginResult.getPrincipal().getClass().getName(), loginResult);
        //从认证结果中获取Principal,本质上是User类型，且是UserDetailService中loadUserByUsername()返回的结果
        log.debug("尝试获取Principal:{}>>>{}", loginResult.getPrincipal().getClass().getName(), loginResult.getPrincipal());
        AdminDetails user = (AdminDetails) loginResult.getPrincipal();
        //                                   ^主体
        String username = user.getUsername();
        log.debug("登录成功的用户名：{}", username);
        Long id = user.getId();
        log.debug("登录成功的id：{}", id);
        Collection<GrantedAuthority> authorities = user.getAuthorities();
        //            ^确认的授权
        log.debug("登录成功的权限：{}", authorities);

        String authoritiesString = JSON.toJSONString(authorities);
        log.debug("将权限转换为JSON：{}", authoritiesString);

        //应该在此处生成JWT数据，向JWT中存入：id(暂无)，username,权限
        Map<String, Object> claims = new HashMap<>();
        //                    ^请求
        claims.put("id",user.getId());
        claims.put("username", user.getUsername());
        claims.put("authorities", authoritiesString);
        String jwt = JwtUtils.generate(claims);
        //                      ^生成
        return jwt;
    }


    @Override
    public List<AdminListItemVO> list() {
        log.debug("开始处理查询管理员列表的业务");
        return mapper.list();
    }

    @Override
    public void deleteById(Long id) {

    }


}

